#pragma once
#include <map>
#include <vector>

namespace Typhoon {
	template<class T>
	class Timeline
	{
	public:

		typedef float Time;

		Timeline();
		~Timeline();

		void Add(Time time, const T& node);
		void Remove(Time time);
		void Clear();

		struct Node {
			Node();
			Time percent;
			T* from;
			T* to;
            int index;
		};
		
		const Node& Get(const Time& time);

		Time StartTime();
		Time EndTime();
		
		bool Empty();
        
        int Count();
        
        void GetNodes(std::vector<T*>& nodes);
		
	private:
		typedef std::map<Time, T> Nodes;
		Nodes nodes;
		Time startTime;
		Time endTime;
		bool isDirty;
		void CalcTime();

		Node node;

	};
}

template<class T>
Typhoon::Timeline<T>::Timeline() {
	startTime = 0;
	endTime = 0;
	isDirty = false;
}

template<class T>
Typhoon::Timeline<T>::~Timeline() {}

template<class T>
void Typhoon::Timeline<T>::Add(Time time, const T& node) {
	nodes[time] = node;
	isDirty = true;
}


template<class T>
void Typhoon::Timeline<T>::Remove(Time time) {
	typename Nodes::iterator it = nodes.find(time);
	if (it==nodes.end()) return;
	nodes.erase(it);
	isDirty = true;
}


template<class T>
void Typhoon::Timeline<T>::Clear() {
    nodes.clear();
    isDirty = true;
    
	//Nodes temp = nodes;
	//for(typename Nodes::iterator it = temp.begin(); it!=temp.end(); ++it) {
	//	Remove(it->first, it->second);
	//}
}

template<class T>
int Typhoon::Timeline<T>::Count() {
    return (int)nodes.size();
}

template<class T>
void Typhoon::Timeline<T>::CalcTime() {
	if (!isDirty) return;
	isDirty = false;
	if (nodes.empty()) return;

	typename Nodes::iterator first = nodes.begin();
	typename Nodes::iterator last = nodes.end();
	--last;
	startTime = first->first;
	endTime = last->first;
}

template<class T>
typename Typhoon::Timeline<T>::Time Typhoon::Timeline<T>::StartTime() {
	CalcTime();
	return startTime;
}

template<class T>
typename Typhoon::Timeline<T>::Time Typhoon::Timeline<T>::EndTime() {
	CalcTime();
	return endTime;
}

template<class T>
Typhoon::Timeline<T>::Node::Node()
{
	from = 0;
	to = 0;
	percent = 0;
}

template<class T>
bool Typhoon::Timeline<T>::Empty()
{
	return nodes.empty();
}

template<class T>
const typename Typhoon::Timeline<T>::Node& Typhoon::Timeline<T>::Get(const Time& time) {
	CalcTime();
	node.percent = 0;
	typename Nodes::iterator it;
	if (time<=startTime) {
		it = nodes.begin();
		node.from = &it->second;
		node.to = &it->second;
        node.index = 0;
		return node;
	}

	if (time>=endTime) {
		it = nodes.end();
		--it;
		node.from = &it->second;
		node.to = &it->second;
        node.index = nodes.size()-1;
		return node;
	}

    int index = nodes.size()-1;
	typename Nodes::iterator previous = nodes.begin();
	for(it = previous; it!=nodes.end(); ++it) {
		if (time<=it->first) {
			node.from = &previous->second;
			node.to = &it->second;
			node.percent = (time - previous->first) / (it->first - previous->first);
            node.index = index;
			return node;
		}
		previous = it;
        index--;
	}
	
	return node;
}

template<class T>
void Typhoon::Timeline<T>::GetNodes(std::vector<T*> &nodesList)
{
	typename Nodes::iterator it;
	for (it = nodes.begin(); it!=nodes.end(); ++it) {
        nodesList.push_back(&it->second);
    }
}

